//
//  APIClient.m
//  FinanceProject
//
//  Created by 陈显摆 on 2025/1/15.
//

#import "APIClient.h"
#import <CommonCrypto/CommonDigest.h>
#import <CommonCrypto/CommonCrypto.h>

@implementation APIClient

static id _instance = nil;

+ (instancetype)sharedInstance {
    
    APIClient *client = [[self alloc] init];
    client.responseSerializer = [AFHTTPResponseSerializer serializer];
    client.requestSerializer.timeoutInterval = 10;
    client.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/plain",@"application/json",@"text/json",@"text/javascript",@"text/html",@"image/jpeg", nil];
//    client.responseSerializer.acceptableContentTypes = [NSSet
//        setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html", @"text/plain",nil];
    
    client.requestSerializer = [AFJSONRequestSerializer serializer];
//    client.responseSerializer = [AFCompoundResponseSerializer serializer];
    
    [client setDataTaskDidReceiveDataBlock:^(NSURLSession * _Nonnull session, NSURLSessionDataTask * _Nonnull dataTask, NSData * _Nonnull data) {
    
        NSLog(@"Request URL: %@", dataTask.originalRequest.URL.absoluteString);  // 打印出完整URL
    }];
    
//    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
//    //添加https认证
//    NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"www_ynzhxf_com" ofType:@".cer"];
//    NSData *dataSou = [NSData dataWithContentsOfFile:cerPath];
//    NSSet *set = [NSSet setWithObjects:dataSou, nil];
//    securityPolicy.allowInvalidCertificates = YES;
//    securityPolicy.validatesDomainName = YES;
//    [securityPolicy setPinnedCertificates:set];
//    //将验证方式赋值给管理者
//    client.securityPolicy = securityPolicy;
    
    return client;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        
        _instance = [super allocWithZone:zone];
    });
    
    return _instance;
}

- (instancetype)init {
    
    static dispatch_once_t onceToken;
    
    dispatch_once(&onceToken, ^{
        
        _instance = [super init];
        
        AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
        [manager startMonitoring];
        
        [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            
            switch (status) {
                    case AFNetworkReachabilityStatusUnknown: {
                        
                    NSLog(@"未知网络");
                }
                    break;
                    case AFNetworkReachabilityStatusNotReachable: {
                        
                    NSLog(@"无法联网");
                }
                    break;
                    case AFNetworkReachabilityStatusReachableViaWiFi: {
                        
                    NSLog(@"当前使用的是WIFI网络");
                }
                    break;
                    case AFNetworkReachabilityStatusReachableViaWWAN: {
                        
                    NSLog(@"当前使用的是2G/3G/4G网络(手机自带网络)");
                }
            }
            
//            [[NSNotificationCenter defaultCenter] postNotificationName:XYNetworkStatusNotification object:@(status)];
        }];
    });
    
    return _instance;
}


#pragma mark - 时间戳
- (NSString *)getNowTime{
    
    //获取当前时间戳
    NSDate* date = [NSDate dateWithTimeIntervalSinceNow:0];//获取当前时间0秒后的时间
    NSTimeInterval time=[date timeIntervalSince1970]*1000;// *1000 是精确到毫秒，不乘就是精确到秒
    NSString *timeSp = [NSString stringWithFormat:@"%.0f", time];
    
    return timeSp;
}

/**
 *  从iOS13开始 MD5被弃用, 现在用SHA256加密
 */
- (NSString *)stringToMD5:(NSString *)str {
    
    // 1.首先将字符串转换成UTF-8编码, 因为MD5加密是基于C语言的,所以要先把字符串转化成C语言的字符串
    const char *fooData = [str UTF8String];
    
    // 2.然后创建一个字符串数组,接收MD5的值
    unsigned char result[CC_SHA1_DIGEST_LENGTH];//result[CC_MD5_DIGEST_LENGTH];
    
    // 3.计算MD5的值, 这是官方封装好的加密方法:把我们输入的字符串转换成16进制的32位数,然后存储到result中
//    CC_MD5(fooData, (CC_LONG)strlen(fooData), result);
    CC_SHA256(fooData, (CC_LONG)strlen(fooData), result);
    
    /*
     第一个参数:要加密的字符串
     第二个参数: 获取要加密字符串的长度
     第三个参数: 接收结果的数组
     */
    
    // 4.创建一个字符串保存加密结果
    NSMutableString *saveResult = [NSMutableString string];
    
    // 5.从result 数组中获取加密结果并放到 saveResult中
    for (int i = 0; i < CC_SHA1_DIGEST_LENGTH /*CC_MD5_DIGEST_LENGTH*/; i++) {
        
        [saveResult appendFormat:@"%02x", result[i]];
        
    }
    
    // x表示十六进制，%02X  意思是不足两位将用0补齐，如果多余两位则不影响
    return saveResult;
    
    /*
     
     这里返回的是32位的加密字符串，有时我们需要的是16位的加密字符串，其实仔细观察即可发现，16位的加密字符串就是这个字符串中见的部分。我们只需要截取字符串即可（[saveResult substringWithRange:NSMakeRange(7, 16)]）
     
     */
    
}

#pragma mark - 网络请求
- (void)requestWithURLString:(NSString *)URLString parameters:(id)parameters type:(HttpRequestType)type success:(void (^)(id, NSString *, NSInteger))success failure:(void (^)(NSError *error))failure {
    
    if ([self getProxyStatus]) {
        
//        [MBManager hideLoading];
//        [MBManager showText:@"有代理"];
        
        if (![self isSimuLator]) {
         
            return;
        }
    }
    
    NSMutableDictionary *headers = NSMutableDictionary.dictionary;
//    [headers setValue:@"application/json" forKey:@"Content－Type"];
    [headers setValue:@"application/json" forKey:@"Content-Type"];
    [headers setValue:@"user" forKey:@"X-User-Type"];
    
    if (FPUserModel.globalToken.length) {
        
        [headers setValue:FPUserModel.globalToken forKey:@"token"];	
    }
    
    switch (type) {
            
        case HttpRequestTypeGet: {
            
//            NSString *time = [self getNowTime];
//            NSString *sign = [NSString stringWithFormat:@"rqb8888&%@",time];
            
//            [self.requestSerializer setValue:@"rqb8888" forHTTPHeaderField:@"key"];
//            [self.requestSerializer setValue:time forHTTPHeaderField:@"timestamp"];
//            [self.requestSerializer setValue:[self stringToMD5:sign] forHTTPHeaderField:@"sign"];
            
//            NSString *sysModel = [UIView systemModel];
//            NSString *sysVersion = [[UIDevice currentDevice] systemVersion];
//            [self.requestSerializer setValue:[NSString stringWithFormat:@"%@_%@",sysModel, sysVersion] forHTTPHeaderField:@"publicParam"];
            
            [self GET:URLString parameters:parameters headers:headers progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                NSError *error;
                id obj = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:&error];
                
                NSInteger code = [[obj objectForKey:@"code"] integerValue];
                
                NSString *msg;
                
                if (code == 401) {

                    [[NSNotificationCenter defaultCenter] postNotificationName:UserTokenInvalidNotification object:nil];
                }
                else if (code == 500) {
                    
                    // 请求失败
                }
                
                if (success) {
                    
                    success(responseObject,msg,code);
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                if (failure) {
                    
                    failure(error);
                }
            }];
        }
            break;
        case HttpRequestTypePost: {
            
//            [self.requestSerializer setValue:@"ios" forHTTPHeaderField:@"device"];
            
//            NSString *sysModel = [UIView systemModel];
//            NSString *sysVersion = [[UIDevice currentDevice] systemVersion];
//            [self.requestSerializer setValue:[NSString stringWithFormat:@"%@_%@",sysModel, sysVersion] forHTTPHeaderField:@"publicParam"];
            
//            NSString *time = [self getNowTime];
//            NSString *sign = [NSString stringWithFormat:@"rqb8888&%@",time];
            
//            [self.requestSerializer setValue:@"rqb8888" forHTTPHeaderField:@"key"];
//            [self.requestSerializer setValue:time forHTTPHeaderField:@"timestamp"];
//            [self.requestSerializer setValue:[self stringToMD5:sign] forHTTPHeaderField:@"sign"];
            self.requestSerializer = [AFJSONRequestSerializer serializer];
            [self POST:URLString parameters:parameters headers:headers progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                
                NSError *error;
                id obj = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:&error];
                
                NSInteger code = [[obj objectForKey:@"code"] integerValue];
                
                NSString *msg;
                
                if ([obj isKindOfClass:NSDictionary.class]) {
                    
                    msg = [obj objectForKey:@"msg"];
                }
                
                if (code == 401) {
                    
                    [[NSNotificationCenter defaultCenter] postNotificationName:UserTokenInvalidNotification object:nil];
                }
                else if (code == 500) {
                    
                    // 请求失败
                }
                
                if (success) {
                    
                    success(responseObject,msg,code);
                }
                
            } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                
                if (failure) {
                    
                    failure(error);
                }
            }];
        }
            break;
    }
}

+ (NSMutableDictionary *)creatAPIDictionary {
    
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    
//    if ([NDUser globalToken].length) {
//
//        if (![[[NDAPIClient sharedInstance].requestSerializer.HTTPRequestHeaders allKeys] containsObject:@"token"]) {
//
//            [dic setObject:[NDUser globalToken] forKey:@"Token"];
//        }
//    }
    
    return dic;
}

- (BOOL)getProxyStatus {

    NSDictionary *proxySettings =  (__bridge NSDictionary *)(CFNetworkCopySystemProxySettings());
    
    NSArray *proxies = (__bridge NSArray *)(CFNetworkCopyProxiesForURL((__bridge CFURLRef _Nonnull)([NSURL URLWithString:@"http://www.baidu.com"]), (__bridge CFDictionaryRef _Nonnull)(proxySettings)));
    
    NSDictionary *settings = [proxies objectAtIndex:0];
    
//    NSLog(@"host=%@", [settings objectForKey:(NSString *)kCFProxyHostNameKey]);
//    NSLog(@"port=%@", [settings objectForKey:(NSString *)kCFProxyPortNumberKey]);
//    NSLog(@"type=%@", [settings objectForKey:(NSString *)kCFProxyTypeKey]);
    
    if ([[settings objectForKey:(NSString *)kCFProxyTypeKey] isEqualToString:@"kCFProxyTypeNone"]) {
        
        //没有设置代理
        return NO;
    }
    else {
        
        //设置代理了
        return YES;
    }
}


- (BOOL)isSimuLator {
    
    if (TARGET_IPHONE_SIMULATOR == 1 && TARGET_OS_IPHONE == 1) {
    
        //模拟器
        return YES;
    }
    else {
        //真机
        return NO;
    }
}
    

#pragma mark - AES加密
//MARK:key
//    OC中的AES加密是通过key的bytes数组位数来进行AES128/192/256加密
//    key -> 加密方式
//    16  -> AES128
//    24  -> AES192
//    32  -> AES256
////MARK: iv
//    iv:偏移量，加密过程中会按照偏移量进行循环位移
- (NSData *)aesEncryptWithData:(NSData *)enData andKey:(NSData *)key iv:(NSData *)iv {
    
    if (key.length != 16 && key.length != 24 && key.length != 32) {
    
        return nil;
    }
    if (iv.length != 16 && iv.length != 0) {
        
        return nil;
    }
    
    NSData *result = nil;
    size_t bufferSize = enData.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    if (!buffer) return nil;
    size_t encryptedSize = 0;
    
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding,//填充方式
                                          key.bytes,
                                          key.length,
                                          iv.bytes,
                                          enData.bytes,
                                          enData.length,
                                          buffer,
                                          bufferSize,
                                          &encryptedSize);
    if (cryptStatus == kCCSuccess) {
    
        result = [[NSData alloc]initWithBytes:buffer length:encryptedSize];
        free(buffer);
        return result;
    }
    else {
    
        free(buffer);
        return nil;
    }
}


- (NSData *)aesDecryptWithData:(NSData *)deData andKey:(NSData *)key iv:(NSData *)iv {
    
    if (key.length != 16 && key.length != 24 && key.length != 32) {
    
        return nil;
    }
    
    if (iv.length != 16 && iv.length != 0) {
    
        return nil;
    }
    
    NSData *result = nil;
    size_t bufferSize = deData.length + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);
    
    if (!buffer) return nil;
    
    size_t encryptedSize = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
                                          kCCAlgorithmAES128,
                                          kCCOptionPKCS7Padding,//填充方式
                                          key.bytes,
                                          key.length,
                                          iv.bytes,
                                          deData.bytes,
                                          deData.length,
                                          buffer,
                                          bufferSize,
                                          &encryptedSize);
    if (cryptStatus == kCCSuccess) {
    
        result = [[NSData alloc]initWithBytes:buffer length:encryptedSize];
        free(buffer);
        return result;
    }
    else {
    
        free(buffer);
        return nil;
    }
}

+ (NSString *)getQueryURLStringWithParam:(NSDictionary *)queryParams URLString:(NSString *)URLStr {
    
    // 构造完整的 URL，包括查询参数
    NSMutableString *urlWithQuery = [NSMutableString stringWithString:URLStr];
    
    BOOL isFirstParam = YES;
    
    for (NSString *key in queryParams) {
    
        NSString *value = queryParams[key];
        
        if (isFirstParam) {
        
            [urlWithQuery appendFormat:@"?%@=%@", key, value];
            isFirstParam = NO;
        }
        else {
        
            [urlWithQuery appendFormat:@"&%@=%@", key, value];
        }
    }
    
    // 输出最终的完整 URL
    NSLog(@"Request URL: %@", urlWithQuery);
    
    return urlWithQuery;
}


@end
